package com.boil.util;

import com.boil.exception.BaseException;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.converter.ExcelToHtmlConverter;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.FileURIResolver;
import org.apache.poi.xwpf.converter.core.IImageExtractor;
import org.apache.poi.xwpf.converter.core.IURIResolver;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;

/**
 * Created by ChenYong on 2017-06-02.
 * <br>
 * 办公软件工具类。
 */
public class OfficeUtils {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(OfficeUtils.class);

    /**
     * 写文件。
     *
     * @param filePath    文件路径
     * @param fileContent 文件内容
     */
    private static void writeFile(String filePath, String fileContent) throws BaseException {
        // 声明输出流
        FileOutputStream fileOutputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        BufferedWriter bufferedWriter = null;

        try {
            if (StringUtils.isBlank(filePath) || StringUtils.isBlank(fileContent)) {
                throw new BaseException("OfficeUtils--->写文件时，文件路径/文件内容为空");
            }

            // 美化 Html
            // fileContent = fileContent.replace(Constants.HEAD_TAG, String.format("%s%s", Constants.HEAD_TAG, Constants.HTML5_TAG));

            fileOutputStream = new FileOutputStream(filePath);
            outputStreamWriter = new OutputStreamWriter(fileOutputStream, Constants.UTF_8);
            bufferedWriter = new BufferedWriter(outputStreamWriter);

            bufferedWriter.write(fileContent);
        } catch (Exception e) {
            throw new BaseException(e);
        } finally {
            try {
                if (bufferedWriter != null) {
                    bufferedWriter.close();
                }

                if (outputStreamWriter != null) {
                    outputStreamWriter.close();
                }

                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (Exception e) {
            }
        }
    }

    /**
     * 写文件。
     *
     * @param filePath    文件路径
     * @param fileContent 文件内容
     */
    private static void writeFile(String filePath, byte[] fileContent) throws BaseException {
        // 声明输出流
        FileOutputStream fileOutputStream = null;

        try {
            if (StringUtils.isBlank(filePath) || (fileContent == null) || (fileContent.length == Constants.VALUE_0)) {
                throw new BaseException("OfficeUtils--->写文件时，文件路径/文件内容为空");
            }

            fileOutputStream = new FileOutputStream(filePath);

            fileOutputStream.write(fileContent);
        } catch (Exception e) {
            throw new BaseException(e);
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (Exception e) {
            }
        }
    }

    /**
     * 将 Word 文件 doc 格式转换为 Html。
     *
     * @param wordDoc  Word 文件
     * @param htmlPath Html 的路径
     */
    public static void doc2Html(final File wordDoc, final String htmlPath) throws BaseException {
        // 声明输入流
        FileInputStream fileInputStream = null;
        // 声明输出流
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {
            if ((wordDoc == null) || (wordDoc.length() == Constants.VALUE_L_0) || StringUtils.isBlank(htmlPath)) {
                throw new BaseException("OfficeUtils--->将Word文件doc格式转换为Html时，Word文件/Html路径为空");
            }

            // html 文件路径
            String htmlFilePath = String.format("%s/%s%s%s", htmlPath, FileUtils.getFileNameNoSuffix(wordDoc.getName()), Constants.POINT_CHAR, Constants.SUFFIX_HTML);

            fileInputStream = new FileInputStream(wordDoc);
            byteArrayOutputStream = new ByteArrayOutputStream();

            // Word
            HWPFDocument hwpfDocument = new HWPFDocument(fileInputStream);
            // Word 与 Html 的转换器
            WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());

            // 保存图片，并返回图片的相对路径
            wordToHtmlConverter.setPicturesManager(new PicturesManager() {
                @Override
                public String savePicture(byte[] bytes, PictureType pictureType, String s, float v1, float v2) {
                    writeFile(String.format("%s/%s/%s%s%s", //
                            htmlPath, //
                            Constants.IMAGE_STR, //
                            FileUtils.getFileNameNoSuffix(wordDoc.getName()), //
                            Constants.UNDERLINE_CHAR, //
                            s), bytes);

                    return String.format("%s/%s%s%s", Constants.IMAGE_STR, FileUtils.getFileNameNoSuffix(wordDoc.getName()), Constants.UNDERLINE_CHAR, s);
                }
            });

            wordToHtmlConverter.processDocument(hwpfDocument);

            Document document = wordToHtmlConverter.getDocument();
            DOMSource domSource = new DOMSource(document);
            StreamResult streamResult = new StreamResult(byteArrayOutputStream);
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();

            transformer.setOutputProperty(OutputKeys.ENCODING, Constants.UTF_8);
            transformer.setOutputProperty(OutputKeys.INDENT, Constants.YES);
            transformer.setOutputProperty(OutputKeys.METHOD, Constants.SUFFIX_HTML);
            transformer.transform(domSource, streamResult);

            String htmlStr = new String(byteArrayOutputStream.toByteArray(), Constants.UTF_8);

            writeFile(htmlFilePath, htmlStr);
        } catch (Exception e) {
            throw new BaseException(e);

            // 释放资源
        } finally {
            try {
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }

                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (Exception e) {
            }
        }
    }

    /**
     * 将 Word 文件 docx 格式转换为 Html。
     *
     * @param wordDocx Word 文件
     * @param htmlPath Html 路径
     */
    public static void docx2Html(final File wordDocx, final String htmlPath) throws BaseException {
        // 声明输入流
        FileInputStream fileInputStream = null;
        // 声明输出流
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {
            if ((wordDocx == null) || (wordDocx.length() == Constants.VALUE_L_0) || StringUtils.isBlank(htmlPath)) {
                throw new BaseException("OfficeUtils--->将Word文件docx格式转换为Html时，Word文件/Html路径为空");
            }

            // html 文件路径
            String htmlFilePath = String.format("%s/%s%s%s", htmlPath, FileUtils.getFileNameNoSuffix(wordDocx.getName()), Constants.POINT_CHAR, Constants.SUFFIX_HTML);

            fileInputStream = new FileInputStream(wordDocx);
            byteArrayOutputStream = new ByteArrayOutputStream();

            // Word
            XWPFDocument xwpfDocument = new XWPFDocument(fileInputStream);
            // 配置
            XHTMLOptions xhtmlOptions = XHTMLOptions.create().URIResolver(new FileURIResolver(new File(String.format("%s/%s/", htmlPath, Constants.IMAGE_STR))));

            // 保存图片
            xhtmlOptions.setExtractor(new IImageExtractor() {
                @Override
                public void extract(String s, byte[] bytes) throws IOException {
                    writeFile(String.format("%s/%s/%s%s%s", //
                            htmlPath, //
                            Constants.IMAGE_STR, //
                            FileUtils.getFileNameNoSuffix(wordDocx.getName()), //
                            Constants.UNDERLINE_CHAR, //
                            s.substring(s.lastIndexOf(Constants.BACKSLASH_CHAR) + Constants.VALUE_1)), bytes);
                }
            });
            // 设置图片的相对路径
            xhtmlOptions.URIResolver(new IURIResolver() {
                @Override
                public String resolve(String s) {
                    return String.format("%s/%s%s%s", Constants.IMAGE_STR, //
                            FileUtils.getFileNameNoSuffix(wordDocx.getName()), //
                            Constants.UNDERLINE_CHAR, //
                            s.substring(s.lastIndexOf(Constants.BACKSLASH_CHAR) + Constants.VALUE_1));
                }
            });

            XHTMLConverter.getInstance().convert(xwpfDocument, byteArrayOutputStream, xhtmlOptions);

            String htmlStr = new String(byteArrayOutputStream.toByteArray(), Constants.UTF_8);

            writeFile(htmlFilePath, htmlStr);
        } catch (Exception e) {
            throw new BaseException(e);

            // 释放资源
        } finally {
            try {
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }

                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (Exception e) {
            }
        }
    }

    /**
     * 将 Excel 文件 xls 格式转换为 Html。
     *
     * @param excelXls Excel 文件
     * @param htmlPath Html 路径
     */
    public static void xls2Html(File excelXls, String htmlPath) throws BaseException {
        // 声明输入流
        FileInputStream fileInputStream = null;
        // 声明输出流
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {
            if ((excelXls == null) || (excelXls.length() == Constants.VALUE_L_0) || StringUtils.isBlank(htmlPath)) {
                throw new BaseException("OfficeUtils--->将Excel文件xls格式转换为Html时，Excel文件/Html路径为空");
            }

            // html 文件路径
            String htmlFilePath = String.format("%s/%s%s%s", htmlPath, FileUtils.getFileNameNoSuffix(excelXls.getName()), Constants.POINT_CHAR, Constants.SUFFIX_HTML);

            fileInputStream = new FileInputStream(excelXls);
            byteArrayOutputStream = new ByteArrayOutputStream();

            // Excel
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook(fileInputStream);
            ExcelToHtmlConverter excelToHtmlConverter = new ExcelToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());

            excelToHtmlConverter.setOutputColumnHeaders(false);
            excelToHtmlConverter.setOutputRowNumbers(false);
            excelToHtmlConverter.processWorkbook(hssfWorkbook);

            Document document = excelToHtmlConverter.getDocument();
            DOMSource domSource = new DOMSource(document);
            StreamResult streamResult = new StreamResult(byteArrayOutputStream);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.ENCODING, Constants.UTF_8);
            transformer.setOutputProperty(OutputKeys.INDENT, Constants.YES);
            transformer.setOutputProperty(OutputKeys.METHOD, Constants.SUFFIX_HTML);
            transformer.transform(domSource, streamResult);

            String htmlStr = new String(byteArrayOutputStream.toByteArray(), Constants.UTF_8);

            htmlStr = htmlStr.replace("<h2>Sheet1</h2>", Constants.EMPTY_STR) //
                    .replace("<h2>Sheet2</h2>", Constants.EMPTY_STR) //
                    .replace("<h2>Sheet3</h2>", Constants.EMPTY_STR) //
                    .replace("<h2>Sheet4</h2>", Constants.EMPTY_STR) //
                    .replace("<h2>Sheet5</h2>", Constants.EMPTY_STR);

            writeFile(htmlFilePath, htmlStr);
        } catch (Exception e) {
            throw new BaseException(e);

            // 释放资源
        } finally {
            try {
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }

                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (Exception e) {
            }
        }
    }
}